// Burn - Arcade emulator library - internal code
#ifndef BURNINT_H
#define BURNINT_H

// Standard headers
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "burn.h"

// ------------------------------------------------------------------
// CPU emulation interfaces

typedef union
{
	struct { UINT8 l,h,h2,h3; } b;
	struct { UINT16 l,h; } w;
	UINT32 d;
} PAIR;

// sek.cpp
#include "sek.h"

// zet.cpp
#include "zet.h"

// ------------------------------------------------------------------
// Driver information

struct BurnDriver {
	const char* shortName;		// The filename of the zip file (without extension)
	const char* parentName;		// The filename of the parent (without extension, NULL if not applicable)
	const char* boardRom;		// The filename of the board ROMs (without extension, NULL if not applicable)
	const char* data;

	// fullName, comment, manufacturer and system should always contain valid info
	const char* fullName; const char* comment; const char* manufacturer; const char* system;

	int flags;			// See burn.h
	int players;		// Max number of players a game supports (so we can remove single player games from netplay)
	int hardware;		// Which type of hardware the game runs on

	int (*getRomInfo)(struct BurnRomInfo* pri, unsigned int i);		// Function to get the length and crc of each rom
	int (*getRomName)(char** name, unsigned int i, int aka);		// Function to get the possible names for each rom
	int (*getInputInfo)(struct BurnInputInfo* pii, unsigned int i);	// Function to get the input info for the game
	int (*getDIPInfo)(struct BurnDIPInfo* pdi, unsigned int i);		// Function to get the input info for the game

	int (*init)(); int (*exit)(); int (*frame)(); int (*redraw)(); int (*scan)(int action, int* min);

	unsigned char* recalcPal;	// Set to 1 if the palette needs to be fully re-calculated
	unsigned width, height;		// Screen width, height
};

#define BurnDriverD BurnDriver		// Debug status
#define BurnDriverX BurnDriver		// Exclude from build

// Standard functions for dealing with ROM and input info structures
#include "stdfunc.h"

// ------------------------------------------------------------------

// Byteswaps an area of memory
static inline int BurnByteswap(UINT8* mem, int len)
{
	len >>= 1;
	for (int i = 0; i < len; i++, mem += 2) {
		UINT8 t = mem[0];
		mem[0] = mem[1];
		mem[1] = t;
	}
	return 0;
}

int BurnClearScreen();

// load.cpp
int BurnLoadRom(UINT8* dest, unsigned i, int gap);
int BurnXorRom(UINT8* dest, unsigned i, int gap);
int BurnLoadBitField(UINT8* dest, UINT8* src, int field, int srcLen);

// ------------------------------------------------------------------
// Colour-depth independant image transfer

extern unsigned short* pTransDraw;

void BurnTransferClear();
int BurnTransferCopy(unsigned int* palette);
void BurnTransferExit();
int BurnTransferInit();

// ------------------------------------------------------------------
// Plotting pixels

static inline void PutPix(UINT8* pix, UINT32 c)
{
	if (nBurnBpp >= 4) {
		*((UINT32*)pix) = c;
	} else {
		if (nBurnBpp == 2) {
			*((UINT16*)pix) = (UINT16)c;
		} else {
			pix[0] = (UINT8)(c >>  0);
			pix[1] = (UINT8)(c >>  8);
			pix[2] = (UINT8)(c >> 16);
		}
	}
}

// ------------------------------------------------------------------
// Clear opposites

static inline void DrvClearOpposites(unsigned char* joystickInputs)
{
	if ((*joystickInputs & 0x03) == 0x03) {
		*joystickInputs &= ~0x03;
	}
	if ((*joystickInputs & 0x0c) == 0x0c) {
		*joystickInputs &= ~0x0c;
	}
}

static inline void DrvClearOpposites(unsigned short* joystickInputs)
{
	if ((*joystickInputs & 0x03) == 0x03) {
		*joystickInputs &= ~0x03;
	}
	if ((*joystickInputs & 0x0c) == 0x0c) {
		*joystickInputs &= ~0x0c;
	}
}

// ------------------------------------------------------------------
// Setting up cpus for cheats

typedef enum {
	CPU_M68K, CPU_VEZ, CPU_SH2, CPU_M6502, CPU_Z80,
	CPU_M6809, CPU_M6805, CPU_HD6309, CPU_M6800, CPU_S2650,
	CPU_KONAMICUSTOM, CPU_ARM7,
} CPU_CHEATTYPE;

void CpuCheatRegister(CPU_CHEATTYPE type, int num);

#endif
